package com.javaobj.auth.security.jwt;

import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtException;
import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;

@Slf4j
public class JWTAuthenticationManager implements AuthenticationManager {

    /**
     * 解析JWT令牌
     */
    private final JwtDecoder jwtDecoder;

    /**
     * JWT转换器
     */
    private  Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter = new JwtAuthenticationConverter();



    public JWTAuthenticationManager(JwtDecoder jwtDecoder) {
        this.jwtDecoder = jwtDecoder;
    }

    public void setJwtAuthenticationConverter(Converter<Jwt, ? extends AbstractAuthenticationToken> jwtAuthenticationConverter) {
        this.jwtAuthenticationConverter = jwtAuthenticationConverter;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {


        BearerTokenAuthenticationToken bearer = (BearerTokenAuthenticationToken) authentication;


        try {

            //解析JWT
            Jwt jwt = this.jwtDecoder.decode(bearer.getToken());

            //转换成认证信息
            AbstractAuthenticationToken token = this.jwtAuthenticationConverter.convert(jwt);

            if(token == null){
                log.warn("", "Cannot to convert authentication, return null.");
                return null;
            }

            //设置数据
            token.setDetails(bearer.getDetails());

            return token;
        } catch (JwtException failed) {
            //JWT 解析失败不处理
            log.error("", failed);
            return null;
        }
    }


}
